<?php
/*
 * Camelot PHP Tools
 *
 * @version 2.0
 * @author Bendsoft
 * @package PHP Tools
 * @subpackage Camelot
 * @license FreeBSD License (www.bendsoft.com/licensing/)
 * 
 */

/**
 * Camelot PHP Tools Exception handling for interitance
 * @author Bendsoft
 */
class CamelotExceptionHandling {
    /**
     * Stores exceptions caused by command execution, if any
     * @var CamelotException
     */
    public $exception;

    /**
     * Status on the command execution
     * @var bool
     */
    public $commandStatus;
}

/**
 * Camelot PHP Tools Exception handling
 * @since 2.0
 * @author Bendsoft
 */
class CamelotException extends Exception {
    /**
     * The Exception type
     * @var string
     */
    public $type;

    /**
     * The primary error message
     * @var string
     */
    public $message;

    /**
     * Error code
     * @var int
     */
    public $code;

    /**
     * The file where the exception occur
     * @var string
     */
    public $file;

    /**
     * Line where the exception occur
     * @var int
     */
    public $line;

    /**
     * The trace array
     * @var array
     */
    public $trace;

    /**
     * The trace as string
     * @var string
     */
    public $traceAsString;

    /**
     * Construct an exception
     * @param object $exc
     * @param int $code
     */
    public function __construct($exc = null, $code = null) {
        switch (get_class($exc)) {
            case "SoapFault":
                $this->SoapFaultException($exc);
                break;

            default:
                if (isset($code)) {
                    // Get the CamelotExceptionObject
                    $exceptions = CamelotExceptionList::instance();
                    $camelotExceptionObject = $exceptions->getException($code);
                    if (isset($camelotExceptionObject)) {
                        $this->type = "ValidationException";
                        $this->code = $camelotExceptionObject->code;
                        $this->message = $camelotExceptionObject->message;
                    }
                }
                break;
        }
        
        // Set the code, if any
        if(!isset($this->code) && isset($code)) {
            $this->code = $code;
        }
        
    }

    /**
     * Handle SoapFault exceptions
     * @param SoapFault $exc
     */
    private function SoapFaultException(SoapFault $exc) {
        $this->type = "SoapFault";
        $this->message = $exc->getMessage();
        $this->code = $exc->getCode();
        $this->file = $exc->getFile();
        $this->line = $exc->getLine();
        $this->trace = $exc->getTrace();
        $this->traceAsString = $exc->getTraceAsString();
    }

}

class CamelotExceptionList extends ArrayObject {

    /**
     * Store instance of singelton
     * @since 2.1
     * @var CamelotExceptionList 
     */
   private static $instance;

   /**
     * Construct or retrieve an instance of singelton
     * @since 2.1
     * @return CamelotExceptionList
     */
   public static function instance()
   {
       if (!isset(self::$instance)) {
           $className = __CLASS__;
           self::$instance = new $className;
       }
       return self::$instance;
   }

    /**
     * Append a CamelotExceptionObject to the list
     * @param CamelotExceptionObject $value
     */
    public function appendSettings(CamelotExceptionObject $value) {
        parent::append($value);
    }

    /**
     * Get exception for a specific row in the CamelotExceptionList instance
     * @param int $code
     * @return CamelotExceptionObject 
     */
    public function getException($code) {
        $exception = null;
        foreach ($this as $exceptionRow) {
            if ($code == $exceptionRow->code) {
                $exception = $exceptionRow;
                return $exception;
            }
        }
        return false;
    }

}

class CamelotExceptionObject {

    /**
     * Internal exception code
     * @var int
     */
    public $code;

    /**
     * Internal exception message
     * @var string
     */
    public $message;

    /**
     * Construct an CamelotExceptionObject
     * @param int $code
     * @param string $message
     */
    public function __construct($code = null, $message = null) {
        $this->code = $code;
        $this->message = $message;
    }

}

?>
